<?php

// 简单工厂:简单工厂的作用是实例化对象,而不需要客户了解这个对象属于哪个具体的子类。
// 这样做的好处是，将我们许多的业务使用到对具体实现类的依赖转移到了工厂类里面，
// 在我们以后想替换实现类的时候只需要修改工厂，而不需要去每个业务里面修改替换。

/**
 * Interface DB
 */
interface DB
{
    /**
     * connect
     * @return mixed
     */
    public function connect();
}

/**
 * Class mysql
 */
class Mysql implements DB
{
    /**
     * connect
     */
    public function connect()
    {
        echo 'this is obj of mysql;';
    }
}

/**
 * Class oracle
 */
class Oracle implements DB
{
    /**
     * connect
     */
    public function connect()
    {
        echo 'this is obj of oracle;';
    }
}

/**
 * 简单工厂实现类1
 * Class SimpleFactory
 */
class SimpleFactory
{
    /**
     * @var array
     */
    protected $typeList;
    
    /**
     * SimpleFactory constructor.
     */
    public function __construct()
    {
        $this->typeList = [
            Mysql::class,
            Oracle::class
        ];
    }
    
    /**
     * 创建数据库对象
     * @param $type
     * @return mixed
     * @throws Exception
     */
    public function create($type)
    {
        if (!array_key_exists($type, $this->typeList)) {
            throw new \Exception("$type is not valid");
        }
        $className = $this->typeList[$type];
        
        return new $className();
    }
}

/**
 * 简单工厂实现类2
 * Class SimpleFactory2
 */
class SimpleFactory2
{
    /**
     * create
     * @param $type
     * @return bool|Mysql|Oracle
     */
    public function create($type)
    {
        switch ($type) {
            case Mysql::class:
                return new Mysql();
                break;
            case Oracle::class:
                return new Oracle();
                break;
            default:
                return false;
                break;
        }
    }
}

// 假如想扩展一个sqlserver数据库驱动，需要修改SimpleFactory1或者SimpleFactory2的部分代码
// 这违反了开放封闭原则，此时可以考虑使用抽象工厂模式

/**
 * Class sqlServer
 */
class SqlServer implements DB
{
    /**
     * connect
     */
    public function connect()
    {
        echo 'this is obj of sqlserver;';
    }
}



